﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Beeflys
{
    public abstract partial class AActor
    {
        private ActorStartNotify actorStartNotify = new ActorStartNotify();

        public async Task<IActorRef> AddChildAsync<TActor>(string name)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1>(string name,
            T1 item1)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1, T2>(string name,
            T1 item1, T2 item2)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1, item2);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1, T2, T3>(string name,
            T1 item1, T2 item2, T3 item3)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1, item2, item3);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1, T2, T3, T4>(string name,
            T1 item1, T2 item2, T3 item3, T4 item4)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1, item2, item3, item4);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1, T2, T3, T4, T5>(string name,
            T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1, item2, item3, item4, item5);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1, T2, T3, T4, T5, T6>(string name,
            T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1, item2, item3, item4, item5, item6);
            return actorRef;
        }

        public async Task<IActorRef> AddChildAsync<TActor, T1, T2, T3, T4, T5, T6, T7>(string name,
            T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
            where TActor : AActor, new()
        {
            var actorRef = await this.actorSystem.AddActorAsync(typeof(TActor), string.Empty, name);
            await actorStartNotify.InvokStartNotifyAsync(actorRef, item1, item2, item3, item4, item5, item6, item7);
            return actorRef;
        }

        internal Task<IActorRef> AddChildAsync(Type type, string host, string name)
        {
            host = string.IsNullOrEmpty(host) ? ActorId.DEFAULT_HOST : host;
            return this.actorSystem.AddActorAsync(type, host, name);
        }
        
        public Task<IEnumerable<IActorRef>> GetChildsAsync()
        {
            return Task.FromResult(this.actorSystem.GetActors());
        }

        public Task<IActorRef> GetChildAsync(string name)
        {
            return this.actorSystem.GetActorAsync(name);
        }
        
        public Task<bool> DelChildAsync(IActorRef actorRef)
        {
            return this.DelChildAsync(actorRef.Id.Name);
        }

        public Task<bool> DelChildAsync(string name)
        {
            return this.actorSystem.DelActorAsync(name);
        }
    }
}